package org.zachary.agent.domain.aggregate_model.user_credit;

import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import org.springframework.data.domain.AbstractAggregateRoot;
import org.zachary.agent.domain.aggregate_model.user.User;
import org.zachary.agent.domain.aggregate_model.user_credit.event.UserCreditInitEvent;

import java.io.Serial;
import java.io.Serializable;
import java.time.Instant;

@Entity
@Table(name = "user_credit")
public class UserCredit extends AbstractAggregateRoot<UserCredit> implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    @Id
    @Getter
    private int id;
    private Integer creditScore;
    private String accountType;
    private String idNumber;
    @Getter
    private double annualIncome;
    private String qualification;
    private String jobType;
    private Instant creditUpdateTime;
    private String maritalStatus;
    private Instant createTime;
    private Instant updateTime;
    @Getter
    private Integer status;
    @Getter
    private String idCardFront;
    @Getter
    private String idCardBack;
    @Getter
    private String workProof;
    @Getter
    private String educationProof;
    @Getter
    private String incomeProof;


    protected UserCredit() {}

    private UserCredit(int id){
        this.id = id;
        this.creditScore=0;
        this.status=0;
        this.createTime = Instant.now();
    }
    private UserCredit(Integer id,String accountType,String idNumber,double annualIncome,
                       String qualification,String jobType,String maritalStatus,String idCardFront,
                       String idCardBack,String workProof,String educationProof,String incomeProof){
        this.id=id;
        this.accountType = accountType;
        this.idNumber = idNumber;
        this.annualIncome = annualIncome;
        this.qualification = qualification;
        this.jobType = jobType;
        this.maritalStatus = maritalStatus;
        this.idCardFront = idCardFront;
        this.idCardBack = idCardBack;
        this.workProof = workProof;
        this.educationProof = educationProof;
        this.incomeProof = incomeProof;

    }
    public static UserCredit init(int id){
        return new UserCredit(id);
    }
    public boolean hasCredit(){
        return !creditScore.equals(0);
    }
    public static UserCredit createUserCredit(Integer id,String accountType,String idNumber,
                                              double annualIncome, String qualification,String jobType,
                                              String maritalStatus,String idCardFront,String idCardBack,
                                              String workProof,String educationProof,String incomeProof){
        return new UserCredit(id,accountType,idNumber,annualIncome,qualification,jobType,maritalStatus,
                idCardFront,idCardBack,workProof,educationProof,incomeProof);
    }
    public void setCreditScore(Integer creditScore,UserCredit userCredit){
        userCredit.creditScore = creditScore;
    }

    @Override
    public String toString() {
        return "UserCredit{" +
                "id=" + id +
                ", creditScore=" + creditScore +
                ", accountType='" + accountType + '\'' +
                ", idNumber='" + idNumber + '\'' +
                ", annualIncome=" + annualIncome +
                ", qualification='" + qualification + '\'' +
                ", jobType='" + jobType + '\'' +
                ", creditUpdateTime=" + creditUpdateTime +
                ", maritalStatus='" + maritalStatus + '\'' +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", status=" + status +
                ", idCardFront='" + idCardFront + '\'' +
                ", idCardBack='" + idCardBack + '\'' +
                ", workProof='" + workProof + '\'' +
                ", educationProof='" + educationProof + '\'' +
                ", incomeProof='" + incomeProof + '\'' +
                '}';
    }

    public void validator(){
        validateAccountType();
        validateIdNumber();
        validateAnnualIncome();
        //validateQualification();
        validateJobType();
        validateMaritalStatus();
    }
    public void validateAccountType(){
        if(this.accountType.isEmpty()){
            throw new IllegalStateException("Account type cannot be empty");
        }
    }
    public void validateIdNumber(){
        if(this.idNumber.isEmpty()){
            throw new IllegalStateException("身份证号不能为空");
        }
        if(this.idNumber.length() != 18){
            throw new IllegalStateException("身份证号为18位");
        }
    }
    public void validateAnnualIncome(){
        if(this.annualIncome<0.0){
            throw new IllegalArgumentException("年入不能为负数");
        }
    }
    public void validateQualification(){
        if(!(this.qualification.equals("专科及以上")||
                this.qualification.equals("高中(含职高)")||
                this.qualification.equals("初中")||
                this.qualification.equals("小学")||
                this.qualification.equals("文盲")||
                this.qualification.equals("半文盲"))){
            throw new IllegalArgumentException("学历参数有误（专科及以上、高中(含职高)、初中、小学、文盲、半文盲）");
        }
    }
    public void validateJobType(){
        if(this.jobType.isEmpty()){
            throw new IllegalStateException("Job type cannot be empty");
        }
    }
    public void validateMaritalStatus(){
        if(!(this.maritalStatus.equals("未婚")||
                this.maritalStatus.equals("已婚")||
                this.maritalStatus.equals("离婚")||
                this.maritalStatus.equals("丧偶"))){
            throw new IllegalArgumentException("婚姻状态参数有误");
        }
    }
    private UserCredit(Integer id,Integer score,String accountType,String idNumber,double annualIncome,
                       String qualification,String jobType,String maritalStatus,Instant updateScoreTime,Integer status){
        this.id=id;
        this.creditScore=score;
        this.accountType = accountType;
        this.idNumber = idNumber;
        this.annualIncome = annualIncome;
        this.qualification = qualification;
        this.jobType = jobType;
        this.maritalStatus = maritalStatus;
        this.creditUpdateTime = updateScoreTime;
        this.status = status;
    }
    public static UserCredit mask(UserCredit uc){
        return new UserCredit(
                uc.id,
                uc.creditScore,
                maskMiddle(uc.accountType,3,4),
                maskMiddle(uc.idNumber,4,2),
                uc.annualIncome,
                uc.qualification,
                uc.jobType,
                uc.maritalStatus,
                uc.creditUpdateTime,
                uc.status
        );
    }

    public static String maskMiddle(String text, int prefixLen, int suffixLen) {
        if (text == null || text.isEmpty()) return text;
        int n = text.length();
        if (n <= prefixLen + suffixLen) {
            return n <= 2 ? "*".repeat(n) : text.charAt(0) + "*".repeat(n-2) + text.charAt(n-1);
        }
        return text.substring(0, prefixLen)
                + "*".repeat(n - prefixLen - suffixLen)
                + text.substring(n - suffixLen);
    }

    public Integer getCreditScore() {
        return creditScore==null?-1:creditScore;
    }

    public String getAccountType() {
        return accountType==null?"未设置":accountType;
    }

    public String getIdNumber() {
        return idNumber==null?"未设置":idNumber;
    }

    public String getQualification() {
        return qualification==null?"未设置":qualification;
    }

    public String getJobType() {
        return jobType==null?"未设置":jobType;
    }

    public Instant getCreditUpdateTime() {
        return creditUpdateTime==null?Instant.now():creditUpdateTime;
    }

    public String getMaritalStatus() {
        return maritalStatus==null?"未设置":maritalStatus;
    }

    public Instant getCreateTime() {
        return createTime==null?Instant.now():createTime;
    }

    public Instant getUpdateTime() {
        return updateTime==null?Instant.now():updateTime;
    }

}
